package sz2;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Proxy;

public class ValidationProxy {
    public static Object newInstance(Object target) {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),new ValidationInvocationHandler(target));
    }

    private static class ValidationInvocationHandler implements InvocationHandler {
        private final Object target;
        public ValidationInvocationHandler(Object target) {
            this.target = target;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Method[] methods = target.getClass().getInterfaces()[0].getMethods();
            for (Method method1 : methods) {
                if (method1.getName().equals(method.getName()) && method1.getParameterCount() == args.length) {
                    Parameter[] parameters = method1.getParameters();
                    for (int i = 0; i < parameters.length; i++) {
                        if (parameters[i].isAnnotationPresent(Validate.class)) {
                            Validate validate = parameters[i].getAnnotation(Validate.class);
                            Object value = args[i];
                            if(value instanceof Double){
                                Double d = (Double)value;
                                if(validate.notEmpty() && d==null){
                                    throw  new ValidationException("Parameter cannot be null");
                                }
                                if(!Double.isInfinite(validate.minValue()) && d < validate.minValue()){
                                    throw  new ValidationException("Parameter cannot be negative");
                                }
                                if(!Double.isInfinite(validate.maxValue()) && d > validate.maxValue()){
                                    throw  new ValidationException("Parameter cannot be positive");
                                }
                            }else{
                                throw  new IllegalArgumentException("Unsupported parameter"+args.getClass().getName());
                            }
                        }
                    }
                }
            }
            return method.invoke(target, args);
        }
    }
}
